<!DOCTYPE html>


<html>
<!--
Copyright 2007 The Closure Library Authors. All Rights Reserved.

Use of this source code is governed by the Apache License, Version 2.0.
See the COPYING file for details.
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>goog.dom.pattern Tests</title>
<script src="../../base.js"></script>
<script type="text/javascript">
  goog.require('goog.dom');
  goog.require('goog.dom.TagWalkType');
  goog.require('goog.dom.pattern.AllChildren');
  goog.require('goog.dom.pattern.ChildMatches');
  goog.require('goog.dom.pattern.EndTag');
  goog.require('goog.dom.pattern.FullTag');
  goog.require('goog.dom.pattern.MatchType');
  goog.require('goog.dom.pattern.NodeType');
  goog.require('goog.dom.pattern.Repeat');
  goog.require('goog.dom.pattern.Sequence');
  goog.require('goog.dom.pattern.StartTag');
  goog.require('goog.dom.pattern.Text');
  goog.require('goog.testing.jsunit');
</script>
</head>
<body>
  <div id="div1">
    <span id="span1" style="color: red"></span>
  </div>
  <div id="div2">
    <span id="span2" style="color: blue">x</span>
  </div>
  <div id="div3">Text</div>
  <div id="div4">Other Text</div>
  <span></span>

  <!-- This chunk gets deleted! -->
  <p id="p1"><b>x</b><b>y</b><i>z</i></p>

  <div id="div5"><b id="b1">x</b><b id="b2">y</b><i id="i1">z</i></div>

  <span id="span3"><span><span>X</span></span></span>

  <div id="nodeTypes"><!-- Comment -->Text</div>

<script type="text/javascript">
  // TODO(robbyw): write a test that checks if backtracking works in Sequence

  function testStartTag() {
    var pattern = new goog.dom.pattern.StartTag('DIV');
    assertEquals(
        'StartTag(div) should match div',
        goog.dom.pattern.MatchType.MATCH,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'StartTag(div) should not match span',
        goog.dom.pattern.MatchType.NO_MATCH,
        pattern.matchToken(
            goog.dom.getElement('span1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'StartTag(div) should not match /div',
        goog.dom.pattern.MatchType.NO_MATCH,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.END_TAG));
  }

  function testStartTagCase() {
    var pattern = new goog.dom.pattern.StartTag('diV');
    assertEquals(
        'StartTag(diV) should match div',
        goog.dom.pattern.MatchType.MATCH,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'StartTag(diV) should not match span',
        goog.dom.pattern.MatchType.NO_MATCH,
        pattern.matchToken(
            goog.dom.getElement('span1'),
            goog.dom.TagWalkType.START_TAG));
  }

  function testStartTagRegex() {
    var pattern = new goog.dom.pattern.StartTag(/D/);
    assertEquals(
        'StartTag(/D/) should match div',
        goog.dom.pattern.MatchType.MATCH,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'StartTag(/D/) should not match span',
        goog.dom.pattern.MatchType.NO_MATCH,
        pattern.matchToken(
            goog.dom.getElement('span1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'StartTag(/D/) should not match /div',
        goog.dom.pattern.MatchType.NO_MATCH,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.END_TAG));
  }

  function testStartTagAttributes() {
    var pattern = new goog.dom.pattern.StartTag('DIV',{id: 'div1'});
    assertEquals(
        'StartTag(div,id:div1) should match div1',
        goog.dom.pattern.MatchType.MATCH,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals('StartTag(div,id:div2) should not match div1',
        goog.dom.pattern.MatchType.NO_MATCH,
        pattern.matchToken(
            goog.dom.getElement('div2'),
            goog.dom.TagWalkType.START_TAG));
  }

  function testStartTagStyle() {
    var pattern = new goog.dom.pattern.StartTag('SPAN',null,{color: 'red'});
    assertEquals(
        'StartTag(span,null,color:red) should match span1',
        goog.dom.pattern.MatchType.MATCH,
        pattern.matchToken(
            goog.dom.getElement('span1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'StartTag(span,null,color:blue) should not match span1',
        goog.dom.pattern.MatchType.NO_MATCH,
        pattern.matchToken(
            goog.dom.getElement('span2'),
            goog.dom.TagWalkType.START_TAG));
  }

  function testStartTagAttributeRegex() {
    var pattern = new goog.dom.pattern.StartTag('SPAN',{id: /span\d/});
    assertEquals(
        'StartTag(span,id:/span\\d/) should match span1',
        goog.dom.pattern.MatchType.MATCH,
        pattern.matchToken(
            goog.dom.getElement('span1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'StartTag(span,id:/span\\d/) should match span2',
        goog.dom.pattern.MatchType.MATCH,
        pattern.matchToken(
            goog.dom.getElement('span1'),
            goog.dom.TagWalkType.START_TAG));
  }

  function testEndTag() {
    var pattern = new goog.dom.pattern.EndTag('DIV');
    assertEquals(
        'EndTag should match div',
        goog.dom.pattern.MatchType.MATCH,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.END_TAG));
  }

  function testEndTagRegex() {
    var pattern = new goog.dom.pattern.EndTag(/D/);
    assertEquals(
        'EndTag(/D/) should match /div',
        goog.dom.pattern.MatchType.MATCH,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.END_TAG));
    assertEquals(
        'EndTag(/D/) should not match /span',
        goog.dom.pattern.MatchType.NO_MATCH,
        pattern.matchToken(
            goog.dom.getElement('span1'),
            goog.dom.TagWalkType.END_TAG));
    assertEquals(
        'EndTag(/D/) should not match div',
        goog.dom.pattern.MatchType.NO_MATCH,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.START_TAG));
  }

  function testChildMatches() {
    var pattern = new goog.dom.pattern.ChildMatches(
        new goog.dom.pattern.StartTag('DIV'), 2);

    assertEquals(
        'ChildMatches should match div',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'ChildMatches should match /div',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.END_TAG));
    assertEquals(
        'ChildMatches should match div',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('div2'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'ChildMatches should match /div',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('div2'),
            goog.dom.TagWalkType.END_TAG));
    assertEquals(
        'ChildMatches should finish match at /body',
        goog.dom.pattern.MatchType.BACKTRACK_MATCH,
        pattern.matchToken(
            document.body,
            goog.dom.TagWalkType.END_TAG));

    assertEquals(
        'ChildMatches should match div',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('div2'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'ChildMatches should match /div',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('div2'),
            goog.dom.TagWalkType.END_TAG));
    assertEquals(
        'ChildMatches should fail to match at /body: not enough child matches',
        goog.dom.pattern.MatchType.NO_MATCH,
        pattern.matchToken(
            document.body,
            goog.dom.TagWalkType.END_TAG));
  }

  function testFullTag() {
    var pattern = new goog.dom.pattern.FullTag('DIV');
    assertEquals(
        'FullTag(div) should match div',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'FullTag(div) should match /div',
        goog.dom.pattern.MatchType.MATCH,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.END_TAG));

    assertEquals(
        'FullTag(div) should start match at div',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'FullTag(div) should continue to match span',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('span1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'FullTag(div) should continue to match /span',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('span1'),
            goog.dom.TagWalkType.END_TAG));
    assertEquals(
        'FullTag(div) should finish match at /div',
        goog.dom.pattern.MatchType.MATCH,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.END_TAG));
  }

  function testAllChildren() {
    var pattern = new goog.dom.pattern.AllChildren();
    assertEquals(
        'AllChildren(div) should match div',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'AllChildren(div) should match /div',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.END_TAG));
    assertEquals(
        'AllChildren(div) should match at /body',
        goog.dom.pattern.MatchType.BACKTRACK_MATCH,
        pattern.matchToken(
            document.body,
            goog.dom.TagWalkType.END_TAG));

    assertEquals(
        'AllChildren(div) should start match at div',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'AllChildren(div) should continue to match span',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('span1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'AllChildren(div) should continue to match /span',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('span1'),
            goog.dom.TagWalkType.END_TAG));
    assertEquals(
        'AllChildren(div) should continue to match at /div',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.END_TAG));
    assertEquals(
        'AllChildren(div) should finish match at /body',
        goog.dom.pattern.MatchType.BACKTRACK_MATCH,
        pattern.matchToken(
            document.body,
            goog.dom.TagWalkType.END_TAG));
  }

  function testText() {
    var pattern = new goog.dom.pattern.Text('Text');
    assertEquals(
        'Text should match div3/text()',
        goog.dom.pattern.MatchType.MATCH,
        pattern.matchToken(
            goog.dom.getElement('div3').firstChild,
            goog.dom.TagWalkType.OTHER));
    assertEquals(
        'Text should not match div4/text()',
        goog.dom.pattern.MatchType.NO_MATCH,
        pattern.matchToken(
            goog.dom.getElement('div4').firstChild,
            goog.dom.TagWalkType.OTHER));
    assertEquals(
        'Text should not match div3',
        goog.dom.pattern.MatchType.NO_MATCH,
        pattern.matchToken(
            goog.dom.getElement('div3'),
            goog.dom.TagWalkType.START_TAG));

  }

  function testTextRegex() {
    var pattern = new goog.dom.pattern.Text(/Text/);
    assertEquals(
        'Text(regex) should match div3/text()',
        goog.dom.pattern.MatchType.MATCH,
        pattern.matchToken(
            goog.dom.getElement('div3').firstChild,
            goog.dom.TagWalkType.OTHER));
    assertEquals(
        'Text(regex) should match div4/text()',
        goog.dom.pattern.MatchType.MATCH,
        pattern.matchToken(
            goog.dom.getElement('div4').firstChild,
            goog.dom.TagWalkType.OTHER));
  }

  function testNodeType() {
    var pattern = new goog.dom.pattern.NodeType(goog.dom.NodeType.COMMENT);
    assertEquals('Comment matcher should match a comment',
        goog.dom.pattern.MatchType.MATCH,
        pattern.matchToken(
            goog.dom.getElement('nodeTypes').firstChild,
            goog.dom.TagWalkType.OTHER));
    assertEquals('Comment matcher should not match a text node',
        goog.dom.pattern.MatchType.NO_MATCH,
        pattern.matchToken(
            goog.dom.getElement('nodeTypes').lastChild,
            goog.dom.TagWalkType.OTHER));
  }

  function testSequence() {
    var pattern = new goog.dom.pattern.Sequence([
        new goog.dom.pattern.StartTag('DIV'),
        new goog.dom.pattern.StartTag('SPAN'),
        new goog.dom.pattern.EndTag('SPAN'),
        new goog.dom.pattern.EndTag('DIV')]);

    assertEquals(
        'Sequence[0] should match div1',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'Sequence[1] should match span1',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('span1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'Sequence[2] should match /span1',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('span1'),
            goog.dom.TagWalkType.END_TAG));
    assertEquals(
        'Sequence[3] should match /div1',
        goog.dom.pattern.MatchType.MATCH,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.END_TAG));

    assertEquals(
        'Sequence[0] should match div1 again',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'Sequence[1] should match span1 again',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('span1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'Sequence[2] should match /span1 again',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('span1'),
            goog.dom.TagWalkType.END_TAG));
    assertEquals(
        'Sequence[3] should match /div1 again',
        goog.dom.pattern.MatchType.MATCH,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.END_TAG));

    assertEquals(
        'Sequence[0] should match div1',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'Sequence[1] should not match div1',
        goog.dom.pattern.MatchType.NO_MATCH,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.START_TAG));

    assertEquals(
        'Sequence[0] should match div1 after failure',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'Sequence[1] should match span1 after failure',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('span1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'Sequence[2] should match /span1 after failure',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('span1'),
            goog.dom.TagWalkType.END_TAG));
    assertEquals(
        'Sequence[3] should match /div1 after failure',
        goog.dom.pattern.MatchType.MATCH,
        pattern.matchToken(
            goog.dom.getElement('div1'),
            goog.dom.TagWalkType.END_TAG));
  }

  function testRepeat() {
    var pattern = new goog.dom.pattern.Repeat(
        new goog.dom.pattern.StartTag('B'));

    // Note: this test does not mimic an actual matcher because it is only
    // passing the START_TAG events.

    assertEquals(
        'Repeat[B] should match b1',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('b1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'Repeat[B] should match b2',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('b2'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'Repeat[B] should backtrack match i1',
        goog.dom.pattern.MatchType.BACKTRACK_MATCH,
        pattern.matchToken(
            goog.dom.getElement('i1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'Repeat[B] should have match count of 2',
        2,
        pattern.count);

    assertEquals(
        'Repeat[B] should backtrack match i1 even with no b matches',
        goog.dom.pattern.MatchType.BACKTRACK_MATCH,
        pattern.matchToken(
            goog.dom.getElement('i1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'Repeat[B] should have match count of 0',
        0,
        pattern.count);
  }

  function testRepeatWithMinimum() {
    var pattern = new goog.dom.pattern.Repeat(
        new goog.dom.pattern.StartTag('B'), 1);

    // Note: this test does not mimic an actual matcher because it is only
    // passing the START_TAG events.

    assertEquals(
        'Repeat[B,1] should match b1',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('b1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'Repeat[B,1] should match b2',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(
            goog.dom.getElement('b2'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'Repeat[B,1] should backtrack match i1',
        goog.dom.pattern.MatchType.BACKTRACK_MATCH,
        pattern.matchToken(
            goog.dom.getElement('i1'),
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'Repeat[B,1] should have match count of 2',
        2,
        pattern.count);

    assertEquals(
        'Repeat[B,1] should not match i1',
        goog.dom.pattern.MatchType.NO_MATCH,
        pattern.matchToken(
            goog.dom.getElement('i1'),
            goog.dom.TagWalkType.START_TAG));
  }

  function testRepeatWithMaximum() {
    var pattern = new goog.dom.pattern.Repeat(
        new goog.dom.pattern.StartTag('B'), 1, 1);

    // Note: this test does not mimic an actual matcher because it is only
    // passing the START_TAG events.

    assertEquals(
        'Repeat[B,1] should match b1',
        goog.dom.pattern.MatchType.MATCH,
        pattern.matchToken(
            goog.dom.getElement('b1'),
            goog.dom.TagWalkType.START_TAG));
  }

  function testSequenceBacktrack() {
    var pattern = new goog.dom.pattern.Sequence([
        new goog.dom.pattern.Repeat(new goog.dom.pattern.StartTag('SPAN')),
        new goog.dom.pattern.Text('X')]);

    var root = goog.dom.getElement('span3');
    assertEquals(
        'Sequence[Repeat[SPAN],"X"] should match span3',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(root, goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'Sequence[Repeat[SPAN],"X"] should match span3.firstChild',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(root.firstChild,
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'Sequence[Repeat[SPAN],"X"] should match span3.firstChild.firstChild',
        goog.dom.pattern.MatchType.MATCHING,
        pattern.matchToken(root.firstChild.firstChild,
            goog.dom.TagWalkType.START_TAG));
    assertEquals(
        'Sequence[Repeat[SPAN],"X"] should finish match text node',
        goog.dom.pattern.MatchType.MATCH,
        pattern.matchToken(root.firstChild.firstChild.firstChild,
            goog.dom.TagWalkType.OTHER));
  }
</script>
</body>
</html>
